package com.tanqidi.arcgisandroid.base.basemap;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.util.Log;

import com.esri.arcgisruntime.arcgisservices.TileInfo;
import com.esri.arcgisruntime.data.TileKey;
import com.esri.arcgisruntime.geometry.Envelope;
import com.esri.arcgisruntime.layers.ImageTiledLayer;
import com.esri.arcgisruntime.layers.WebTiledLayer;
import com.esri.arcgisruntime.mapping.Basemap;
import com.tanqidi.arcgisandroid.App;
import com.tanqidi.arcgisandroid.R;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public class MapBoxCacheTiledLayer extends ImageTiledLayer {
    private String mUrl;//地图服务地址
    private static String CACHE_PATH;//缓存路径

    /**
     * @param url 地图地址
     * @return Basemap
     */
    public static Basemap createBaseMap(String url) {
        WebTiledLayer webTiledLayer = new WebTiledLayer(url);
        Envelope fullExtent = webTiledLayer.getFullExtent();
        Basemap basemap = new Basemap();
        TileInfo tileInfo = webTiledLayer.getTileInfo();
        MapBoxCacheTiledLayer cacheTiledLayer = new MapBoxCacheTiledLayer(url, tileInfo, fullExtent);
        basemap.getBaseLayers().add(cacheTiledLayer);
        return basemap;
    }

    private MapBoxCacheTiledLayer(String url, TileInfo tileInfo, Envelope envelope) {
        super(tileInfo, envelope);
        this.mUrl = url;

        CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + App.app.getString(R.string.app_name) + File.separator + App.app.getString(R.string.basemap_cache);
        File file = new File(CACHE_PATH);
        if (!file.exists()) {//判断文件目录是否存在
            file.mkdirs();
        }
    }

    @Override
    protected byte[] getTile(TileKey tileKey) {
        int level = tileKey.getLevel();
        int col = tileKey.getColumn();
        int row = tileKey.getRow();
        // 若缓存存在则返回缓存字节
        String fileName = col + "_" + row + ".png";
        if (hasCached(level + "", fileName)) {
            //本地存在
            File _cacheLevelDir = new File(CACHE_PATH + "/" + level);
            byte[] cachedBytes = null;
            for (File _file : _cacheLevelDir.listFiles()) {
                if (_file.getName().equals(fileName)) {
                    cachedBytes = new byte[(int) _file.length()];
                    try {
                        FileInputStream _fis = new FileInputStream(_file);
                        _fis.read(cachedBytes);
                        _fis.close();
                        return cachedBytes;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        //本地不存在，从网络加载
        if (isNetworkConnected()) {
            byte[] result = downloadData(level, row, col);
            return result;
        }
        return null;
    }

    /**
     * 判断是否有缓存数据
     *
     * @param level    级别
     * @param fileName 瓦片名称  row_col.png
     * @return
     */
    private boolean hasCached(String level, String fileName) {
        File _cacheLevelDir = new File(CACHE_PATH + "/" + level);
        if (!_cacheLevelDir.exists()) {
            _cacheLevelDir.mkdir();
            return false;
        }
        for (File _file : _cacheLevelDir.listFiles()) {
            if (_file.getName().equals(fileName)) {//存在同名文件
                try {
                    byte[] cachedBytes = new byte[(int) _file.length()];
                    FileInputStream _fis = new FileInputStream(_file);
                    _fis.read(cachedBytes); //文件可读
                    _fis.close();
                    return true;
                } catch (Exception e) {
                    //文件不可读
                    return false;
                }
            }
        }
        //不存在同名文件
        return false;
    }

    /**
     * 是否有网络
     * 需要权限 ACCESS_NETWORK_STATE
     *
     * @return true  or   false
     */
    public static boolean isNetworkConnected() {
        ConnectivityManager mConnectivityManager = (ConnectivityManager) App.app.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
        if (mNetworkInfo != null) {
            return mNetworkInfo.isAvailable();
        }
        return false;

    }

    /**
     * 从网络加载瓦片，并保存本地
     *
     * @param level 级别
     * @param row   行
     * @param col   列
     * @return 瓦片数据
     * <p>
     * "https://api.mapbox.com/styles/v1/tanqidi/ckxehcket2c5214nmxkyar1xa/tiles/256/{level}/{col}/{row}@2x?access_token=pk.eyJ1IjoidGFucWlkaSIsImEiOiJja2I5ZDZzNnQwYmhwMnJwZjEzYjc0emJxIn0.dBbJo1l2tqhBADkEP1GKpw"
     */
    private byte[] downloadData(int level, int row, int col) {
        byte[] result = null;
        try {
            String newUrl = mUrl.replace("{level}", String.valueOf(level)).replace("{col}", String.valueOf(col)).replace("{row}", String.valueOf(row));
            URL url = new URL(newUrl);
            byte[] buf = new byte[1024];
            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
            httpConnection.connect();
            BufferedInputStream is = new BufferedInputStream(httpConnection.getInputStream());
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            int temp = -1;
            while ((temp = is.read(buf)) > 0) {
                bos.write(buf, 0, temp);
            }
            is.close();
            httpConnection.disconnect();
            result = bos.toByteArray();
            saveMapCache(result, col + "_" + row + ".png", level + "");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /*private byte[] downloadData(int level, int row, int col) {
        byte[] result = null;
        try {
            String newUrl = mUrl.replace("{level}", String.valueOf(level)).replace("{col}", String.valueOf(col)).replace("{row}", String.valueOf(row));
            URL url = new URL(newUrl);
            byte[] buf = new byte[1024];
            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
            httpConnection.connect();
            BufferedInputStream is = new BufferedInputStream(httpConnection.getInputStream());
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            //压缩
            Bitmap bitmap = BitmapFactory.decodeStream(is);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);
            result = bos.toByteArray();
            *//*int temp = -1;
            while ((temp = is.read(buf)) > 0) {
                bos.write(buf, 0, temp);
            }*//*
            is.close();
            httpConnection.disconnect();
            result = bos.toByteArray();
            saveMapCache(result, col + "_" + row + ".png", level + "");
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return result;
    }*/

    /**
     * 保存瓦片本地
     *
     * @param bytes    瓦片数据
     * @param fileName 瓦片命名
     * @param level    级别
     */
    private void saveMapCache(byte[] bytes, String fileName, String level) {
        try {
            File _cacheDir = new File(CACHE_PATH);
            if (!_cacheDir.exists()) {
                _cacheDir.mkdir();
            }
            File _cacheLevelDir = new File(CACHE_PATH + "/" + level);
            if (!_cacheLevelDir.exists()) {
                _cacheLevelDir.mkdir();
            }
            File _cacheFile = new File(_cacheLevelDir, fileName);
            _cacheFile.createNewFile();
            FileOutputStream _fos = new FileOutputStream(_cacheFile);
            _fos.write(bytes);
            _fos.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("mapCache", "saveMapCache：" + e.toString());
        }
    }
}


